package com.example.demo.controller;

import com.example.demo.utils.GetMultipartFile;
import com.example.demo.utils.ReadExcelCompress;
import com.example.demo.utils.ReadExcelUtil;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.Objects;
import java.util.zip.ZipEntry;
//import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * @Description 文件上传 multipartFile ---》zip xls xlsx
 * 不支持tar、7z
 * multipartFile ---》zipFile 需经file，会生成额外文件（指定的位置，或临时文件）
 * --读取xls后出现bug“stream closed”，压缩包内有同名文件不能完全读取
 * --创建临时文件（copy也可）可规避；Apache通用的方法 无法通过临时文件读取
 * @Author chenhuiyu
 * @Date 2023/12/6
 */
@RestController
@RequestMapping(value = "/file")
public class FileController {
    @PostMapping("/java/upload")
    public void compressUpload(MultipartFile multipartFile) throws IOException {

        System.err.println("filename:" + multipartFile.getOriginalFilename());
        System.out.println("--------------------");
//        File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
//        // 使用copy会在指定位置生成一个文件
//        FileCopyUtils.copy(multipartFile.getBytes(), file);

        ZipInputStream zipInputStream = new ZipInputStream(multipartFile.getInputStream());
        // 使用临时文件则会在c盘中的temp生成临时的文件
//        File file = File.createTempFile("temp", ".zip");
//        multipartFile.transferTo(file);
//        System.out.println(file.getName());

//        java.util.zip.ZipFile zipFile = new java.util.zip.ZipFile(file); // 区分于Apache

        ZipEntry zipEntry;

        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
            System.out.println("zipEntry:" + zipEntry);
            if (zipEntry.isDirectory()) {
                continue;
            }// 是否为文件夹
            long size = zipEntry.getSize();
            System.out.println(zipEntry.getName() + "-" + size + "字节");
            if (size > 0) {
                // 使用zipFile.getInputStream()，则需要关闭zipFile，即zipFile.close()才能删除临时文件
//                ReadExcelUtil.readExcel(zipEntry.getName(), zipFile.getInputStream(zipEntry), 0);
                ReadExcelUtil.readExcel(zipEntry.getName(), zipInputStream, 0);
//                zipInputStream.closeEntry();
            }
            System.out.println("--------------------");
        }
        System.out.println("********************");
        zipInputStream.closeEntry();
        // 关闭zipFile  关闭对应的流
        zipInputStream.close();
//        zipFile.close();
        // 执行时删除
//        System.out.println(file.delete());
        // jvm关闭时再删除
//        file.deleteOnExit();
    }

    @PostMapping("/compress/zip")
    public void compressZip(MultipartFile multipartFile) throws IOException {
        System.err.println("filename:" + multipartFile.getOriginalFilename());
        System.out.println("--------------------");
        ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream());
//        File file = File.createTempFile("temp", ".zip");
//        multipartFile.transferTo(file);
//        System.out.println(file.getName());
//        ZipFile zipFile = new ZipFile(file);
//        Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
        ZipArchiveEntry zipArchiveEntry;

//        while (entries.hasMoreElements()) {
//            zipArchiveEntry = entries.nextElement();
        while ((zipArchiveEntry = zipArchiveInputStream.getNextZipEntry()) != null) {
            System.out.println("archiveEntry:" + zipArchiveEntry);
            if (zipArchiveEntry.isDirectory()) {
                continue;
            }
            long size = zipArchiveEntry.getSize();
            System.out.println(zipArchiveEntry.getName() + ":" + size);
            if (size > 0) {
//                InputStream inputStream = zipFile.getInputStream(zipArchiveEntry);
//                ReadExcelUtil.readExcel(zipArchiveEntry.getName(), inputStream, 0);
                ReadExcelUtil.readExcel(zipArchiveEntry.getName(), zipArchiveInputStream, 0);
//                inputStream.close();
            }
            System.out.println("--------------------");

        }
        System.out.println("********************");
        zipArchiveInputStream.close();
//        zipFile.close();
//        System.out.println(file.delete());

    }

    @PostMapping("/compress/7z")
    public void compress7z(MultipartFile multipartFile) throws IOException {
        System.err.println("filename:" + multipartFile.getOriginalFilename());
        File file = File.createTempFile("temp", ".7z");
        multipartFile.transferTo(file);

//        SevenZFile sevenZFile = new SevenZFile(new File(fileName));
        SevenZFile sevenZFile = new SevenZFile(file);
        System.out.println(file.getName());
        SevenZArchiveEntry sevenZArchiveEntry;
        while ((sevenZArchiveEntry = sevenZFile.getNextEntry()) != null) {
            if (!sevenZArchiveEntry.isDirectory()) {
                long size = sevenZArchiveEntry.getSize();
                System.out.println(sevenZArchiveEntry.getName() + ":" + size);
                if (size > 0) {
                    ReadExcelUtil.readExcel(sevenZArchiveEntry.getName(), sevenZFile.getInputStream(sevenZArchiveEntry), 0);
                }
            }
        }

        sevenZFile.close();
        System.out.println(file.delete());
        System.out.println("********************");

    }

    @PostMapping("/compress/upload")
    public void readCompress(MultipartFile multipartFile) throws IOException, ArchiveException {
        ArchiveStreamFactory archiveStreamFactory = new ArchiveStreamFactory();
        String extension = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().indexOf(".") + 1);

        System.err.println("filename:" + multipartFile.getOriginalFilename());
        System.out.println(extension);
        System.out.println("--------------------");

        ArchiveInputStream archiveInputStream = archiveStreamFactory.createArchiveInputStream(extension, multipartFile.getInputStream());
        ArchiveEntry archiveEntry;
        while ((archiveEntry = archiveInputStream.getNextEntry()) != null) {
            System.out.println("archiveEntry:" + archiveEntry);
            if (archiveEntry.isDirectory()) {
                continue;
            }
            long size = archiveEntry.getSize();

            System.out.println(archiveEntry.getName() + ":" + size);
            if (size > 0) {
                ReadExcelUtil.readExcel(archiveEntry.getName(), archiveInputStream, 0);
            }
            System.out.println("--------------------");

        }
        System.out.println("********************");
        archiveInputStream.close();

    }

    @PostMapping("/multipart/excel")
//    public void multipart(List<MultipartFile> multipartFiles) throws IOException {
//        MultipartFile multipartFile = multipartFiles.get(1);
    public void multipart(MultipartFile multipartFile) throws IOException {
        String filename = multipartFile.getOriginalFilename();
        if (filename != null && !filename.isEmpty()) {
            System.err.println(filename);
            ReadExcelUtil.readExcel(filename, multipartFile.getInputStream(), 0);
        }

    }
}
